﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using FinanSoft.BusinessLayer;
using System.Data.SqlClient;
using FinanSoft.Entities;
using FinanSoft.Utilities;

namespace FinanSoft.DataLayer
{
    class DocumentDataManager
    {
        #region Singleton

        private DocumentDataManager()
        {}
        /// <summary>
        /// Unica Instancia de esa clase
        /// </suammary>
        private static DocumentDataManager _instance;

        /// <summary>
        /// Metodo para implementar el patrón singleton
        /// </summary>
        /// <returns>Instancia única de la clase</returns>
        public static DocumentDataManager GetInstance() 
        {
            if (_instance == null)
                _instance = new DocumentDataManager();
            return _instance;
        }
        #endregion 

        #region Métodos
               
        /// <summary>
        /// Método que se encarga de leer el encabezado de un documento
        /// de la base de datos y mandar a parsear el xml que el stored procedure 
        /// devuelve para convertirlo en un objeto de tipo Document
        /// </summary>
        /// <returns>Retorna el objeto cuentas especiales</returns>
        public Document GetDocEncabezado(int idDocContable)
        {

            try
            {
                AppConfigReader appConfig = AppConfigReader.GetInstance();
                string spName = Constants.SP_NAME_GET_DOC_ENCABEZADO;
                SqlParameter[] parameters = new SqlParameter[1];
                parameters[0] = new SqlParameter(Constants.SP_PARAM_DOC_ENCABEZADO_DOC_ID, idDocContable);
                Console.WriteLine(parameters[0]);
                Console.WriteLine(Constants.SP_PARAM_DOC_ENCABEZADO_DOC_ID + " *** " + idDocContable);
                SqlDataHelper dataHelper = new SqlDataHelper(appConfig.GetConnectionString(Constants.DB_CONN));
                SqlDataReader result = dataHelper.ExecuteStoredProcedure(spName, parameters);
                if (result.HasRows)
                {
                    result.Read();
                    string xmlString = result.GetString(0);
                    dataHelper.CloseReader();
                    xmlString = Constants.ROOT_NODE_BEGINNING + xmlString + Constants.ROOT_NODE_ENDING;

                    // Se crea un documento XML con el string recibido
                    XmlDocument xmlDoc = new XmlDocument();

                    xmlDoc.LoadXml(xmlString);
                    Document doc = BuildxmlDocEncabezado(xmlDoc);
                    doc.idDocumento = idDocContable;
                    return doc;
                }
                else
                    return new Document();
            }
            catch (Exception ex)
            {
                return null;
            }
        }

        /// <summary>
        /// Método que recibe el documento xml a parsear para convertirlo en un SpecialAccount
        /// </summary>
        /// <param name="xmlPeriod">es el string xml a parsear</param>
        /// <returns>retorna un arreglo de todos los tipos de cuentas especiales</returns>
        public Document BuildxmlDocEncabezado(XmlDocument xmlOpenDoc)
        {
            
            // Aquí llamo a la clase de la base de datos que me regresa el string
            //String xmlString = "";
            XmlNodeList nodeChildren = xmlOpenDoc.FirstChild.ChildNodes;

            Document Doc = new Document();
                      
            
            foreach (XmlNode node in nodeChildren)
            {
                XmlNode nodeDocType = node[Constants.DOC_NODE_NAME];
                
                //Doc.idDocumento = System.Convert.ToInt32(node.Attributes.GetNamedItem(Constants.TAG_NAME_DOC_ID).Value);
                Doc.codigoDocumento = System.Convert.ToInt32(node.Attributes.GetNamedItem(Constants.TAG_NAME_DOC_COD).Value);
                Doc.fechaEmision = DateTime.Parse(node.Attributes.GetNamedItem(Constants.TAG_NAME_DOC_CREATE_DATE).Value);
                Doc.fechaVencimiento = DateTime.Parse(node.Attributes.GetNamedItem(Constants.TAG_NAME_DOC_EXP_DATE).Value);
                Doc.IdMoneda = System.Convert.ToInt32(node.Attributes.GetNamedItem(Constants.TAG_NAME_DOC_CURRENCY).Value);

                Doc.owner = nodeDocType.Attributes.GetNamedItem(Constants.TAG_NAME_DOC_OWNER).Value;
                Doc.cuenta = nodeDocType.Attributes.GetNamedItem(Constants.TAG_NAME_DOC_ACCOUNT).Value;              
            }
            
            return Doc;
        }

        /// <summary>
        /// Método que sen encarga de obtener la lista de artículos para un documento en específico
        /// </summary>
        /// <param name="documentId">Id del documento para el cual se quieren obtener los artículos</param>
        /// <returns>La lista de artículos o detalles de un documento</returns>
        public List<DocDetail> GetDocumentDetails(int documentId)
        {
            List<DocDetail> articles = new List<DocDetail>();
            try
            {
                AppConfigReader appConfig = AppConfigReader.GetInstance();
                string spName = Constants.SP_NAME_GET_DOCUMENT_ARTICLES;
                SqlParameter[] parameters = {
                    new SqlParameter(Constants.SP_PARAM_GET_DOCUMENT_ARTICLES_DOC_ID, documentId)};
                SqlDataHelper dataHelper = new SqlDataHelper(appConfig.GetConnectionString(Constants.DB_CONN));
                SqlDataReader result = dataHelper.ExecuteStoredProcedure(spName, parameters);
                while (result.Read())
                {
                    StoreRoom storeRoom = StoreRoomManager.GetInstance().GetStoreRoom(Convert.ToInt32(result[Constants.SP_COLUMN_GET_DOCUMENT_ARTICLES_ID_STORE]));
                    Item item = ItemManager.GetInstance().GetItem(System.Convert.ToInt32(result[Constants.SP_COLUMN_GET_DOCUMENT_ARTICLES_ID_ARTICLE]));
                    double number = System.Convert.ToDouble(result[Constants.SP_COLUMN_GET_DOCUMENT_ARTICLES_CANTIDAD]);
                    double price = System.Convert.ToDouble(result[Constants.SP_COLUMN_GET_DOCUMENT_ARTICLES_PRECIO]);
                    Tax tax = ConfigurationManager.GetInstance().GetTax(Convert.ToInt32(result[Constants.SP_COLUMN_GET_DOCUMENT_ARTICLES_ID_TIPO_IMPUESTO]));
                    DocDetail detail = new DocDetail(documentId, item, storeRoom, number, price, tax);
                    articles.Add(detail);
                }
                dataHelper.CloseReader();
                return articles;
            }
            catch (Exception ex)
            {
                return null;
            }
        }

        public List<DocService> GetDocumentServices(Document document)
        {
            List<DocService> services = new List<DocService>();
            try
            {
                AppConfigReader appConfig = AppConfigReader.GetInstance();
                string spName = Constants.SP_NAME_GET_DOC_SERVICES;
                SqlParameter[] parameters = {
                    new SqlParameter(Constants.SP_PARAM_GET_DOC_SERVICES_DOC_ID, document.idDocumento)};
                SqlDataHelper dataHelper = new SqlDataHelper(appConfig.GetConnectionString(Constants.DB_CONN));
                SqlDataReader result = dataHelper.ExecuteStoredProcedure(spName, parameters);
                while (result.Read())
                {
                    double cost = Convert.ToDouble(result[Constants.SP_COLUMN_GET_DOC_SERVICES_AMOUNT]);
                    int accId = Convert.ToInt32(result[Constants.SP_COLUMN_GET_DOC_SERVICES_ACC_ID]);
                    string description =  result[Constants.SP_COLUMN_GET_DOC_SERVICES_DESCRIPTION].ToString();
                    int taxId = Convert.ToInt32(result[Constants.SP_COLUMN_GET_DOC_SERVICES_TAX_ID]);
                    services.Add(new DocService(document.idDocumento, accId, taxId, cost, document.IdMoneda, description));
                }
                dataHelper.CloseReader();
                return services;
            }
            catch (Exception ex)
            {
                return null;
            }
        }
        #endregion
    }
}
